﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using Microsoft.Xna.Framework;
using haptic.src.engine.render;
using haptic.src.engine.debug;
using haptic.src.engine.core;

namespace haptic.src.engine.scene
{
    [Serializable]
    public class RootNode : Node
    {
        #region Constructors
        public RootNode()
        {
            m_eType = NodeType.E_ROOT;
            m_oRoot = this;
        }
        #endregion

        #region Edit
        public override void SetRootPos(Vector2 vPos)
        {
            m_vRootPosition = vPos;
            m_eFlags |= Flag.E_LOCAL_CHANGED;
        }
        #endregion

        #region Build
        private void BuildRec(Node oNode)
        {
            if (oNode.oChildren != null)
                for (int i = 0; i < oNode.oChildren.Count; i++)
                {
                    Node oChild = oNode.oChildren[i];
                    m_oNodes.Add(oChild);

                    // Collision nodes
                    if (oChild.eType == Node.NodeType.E_COLLISION)
                    {
                        if (m_oCollisionNodes == null)
                            m_oCollisionNodes = new List<CollisionNode>();
                        m_oCollisionNodes.Add((CollisionNode)oChild);
                    }

                    // Drawable nodes
                    if (oChild.GetType().GetInterface("IDrawable2", false) != null)
                    {
                        if (m_oDrawableNodes == null)
                            m_oDrawableNodes = new List<IDrawable2>();
                        m_oDrawableNodes.Add((IDrawable2)oChild);
                    }

                    // DebugDrawable nodes
                    if (oChild.GetType().GetInterface("IDebugDrawable", false) != null)
                    {
                        if (m_oDebugDrawableNodes == null)
                            m_oDebugDrawableNodes = new List<IDebugDrawable>();
                        m_oDebugDrawableNodes.Add((IDebugDrawable)oChild);
                    }

                    BuildRec(oChild);
                }
        }
        public void Build()
        {
            m_oNodes.Clear();
            BuildRec(this);
        }
        #endregion

        #region Load
        public override Result Load()
        {
            Result oRes = base.Load();
            if (oRes.IsFailed())
                return oRes;
            Build();
            return Result.Success;
        }
        #endregion

        #region Update
        public override void Update(GameTime oTime)
        {
            if ((m_eFlags & Flag.E_LOCAL_CHANGED) != 0)
            {
                m_mWorld = m_mLocal;
                m_mWorld.O += m_vRootPosition;
                m_eFlags &= ~Flag.E_LOCAL_CHANGED;
                foreach (Node oNode in m_oNodes)
                    oNode.EnableFlag(Flag.E_LOCAL_CHANGED);
            }
            foreach (Node oNode in m_oNodes)
            {
                oNode.Update(oTime);
            }
        }
        #endregion

        #region Draw
        public override void Draw(Renderer oRenderer)
        {
            if (m_oDrawableNodes == null)
                return;

            foreach (Node oNode in m_oDrawableNodes)
            {
                oNode.Draw(oRenderer);
            }
        }
        public override void DrawDebug(DebugRenderer oRenderer)
        {
            if (m_oDebugDrawableNodes == null)
                return;

            foreach (Node oNode in m_oDebugDrawableNodes)
            {
                oNode.DrawDebug(oRenderer);
            }
        }
        #endregion

        #region Attributes
        [XmlIgnore]
        public List<Node> m_oNodes = new List<Node>();
        [XmlIgnore]
        public List<CollisionNode> m_oCollisionNodes;
        private List<IDrawable2> m_oDrawableNodes;
        private List<IDebugDrawable> m_oDebugDrawableNodes;
        private Vector2 m_vRootPosition = Vector2.Zero;
        [XmlIgnore]
        public Vector2 vRootPosition 
        {
            get { return m_vRootPosition; }
            set 
            { 
                m_vRootPosition = value;
                m_eFlags |= Flag.E_LOCAL_CHANGED;
            }
        }
        #endregion
    }
}
